
#ifndef ANDISPLAYSDK_USBDISPLAYRECEIVER_H
#define ANDISPLAYSDK_USBDISPLAYRECEIVER_H

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

#define SDK_VERSION                 "1.9.17"

#if defined (_WIN32)
# define USBDISPLAY_SDK_API __declspec(dllexport)
#else
# define USBDISPLAY_SDK_API __attribute__ ((visibility ("default")))
#endif
#include <stdint.h>
#include "KeyCodeConstants.h"


typedef enum _UsbDisplayErrorCode {
    USBDISPLAY_ERROR_OK = 0X00,
    USBDISPLAY_ERROR_PORT_USED = 0X01,
    USBDISPLAY_ERROR_PIN_CODE_SERVER_ADDRESS_INVALID = 0X02,
    USBDISPLAY_ERROR_GET_UID_FAILED = 0X03,
    USBDISPLAY_ERROR_UID_INCOMPATIBLE = 0X04,
    USBDISPLAY_ERROR_VALIDATE_FAILED = 0X05,
    USBDISPLAY_ERROR_EXCEED_MAX_COUNT = 0X06,
    USBDISPLAY_ERROR_CODE_IN_USED = 0X07,
    USBDISPLAY_ERROR_CODE_INCOMPATIBLE = 0X08,
    USBDISPLAY_ERROR_INVALID_PARAMETER = 0X09,
    USBDISPLAY_ERROR_CODE_NEEDED = 0X0A,
    USBDISPLAY_ERROR_CODE_NOT_FOUND = 0X0B,
    USBDISPLAY_ERROR_SERVER_ERROR = 0X0C,

    USBDISPLAY_ERRPR_UPGRADE_FOLDER_NOT_EXIST = 0XA0,
    USBDISPLAY_ERROR_UPGRADE_PACKAGE_CORRUPTED = 0XA1,
    USBDISPLAY_ERROR_USB_DEVICE_NOT_READY = 0XA2,
    USBDISPLAY_ERROR_UPGRADE_CMD_FAILED = 0XA3,
    USBDISPLAY_ERROR_CONFIGURE_FAILED = 0XB1,
    USBDISPLAY_ERROR_UNKNOWN = 0XFF,
} UsbDisplayErrorCode;

typedef enum _UsbDisplayLogLevel {
    USBDISPLAY_LOG_VERBOSE = 0X01,
    USBDISPLAY_LOG_INFO = 0X02,
    USBDISPLAY_LOG_WARN = 0X03,
    USBDISPLAY_LOG_ERROR = 0X04,
    USBDISPLAY_LOG_FATAL = 0X05,
} UsbDisplayLogLevel;


typedef enum _UsbDisplayDeviceHideType {
    USBDISPLAY_HIDE_KICK_OUT_BY_OTHERS = 0X01,
    USBDISPLAY_HIDE_SELF_REQUEST = 0X02,
    USBDISPLAY_HIDE_TIMEOUT = 0X03,
} UsbDisplayDeviceHideType;

typedef enum _UsbDisplayReceiverType {
    USBDISPLAY_RECEIVER_TYPE_NORMAL = 0X01,
    USBDISPLAY_RECEIVER_TYPE_3229 = 0X02,
    USBDISPLAY_RECEIVER_TYPE_3288 = 0X03,
    USBDISPLAY_RECEIVER_TYPE_648 = 0X04,
    USBDISPLAY_RECEIVER_TYPE_828 = 0X05,
    USBDISPLAY_RECEIVER_TYPE_838 = 0X06,
    USBDISPLAY_RECEIVER_TYPE_811 = 0X07,
    USBDISPLAY_RECEIVER_TYPE_3399 = 0X08,
    USBDISPLAY_RECEIVER_TYPE_WINDISPLAY = 0X09,
    USBDISPLAY_RECEIVER_TYPE_SDK_NORMAL = 0X0A,
    USBDISPLAY_RECEIVER_TYPE_SDK_ALIOS = 0X0B,
    USBDISPLAY_RECEIVER_TYPE_2861 = 0X0C,
    USBDISPLAY_RECEIVER_TYPE_3229_YOUNG = 0X0D,
} UsbDisplayReceiverType;

typedef enum _UsbDisplayResolution {
    USBDISPLAY_RESOLUTION_NONE = 0,
    USBDISPLAY_RESOLUTION_240P = 1,
    USBDISPLAY_RESOLUTION_360P = 2,
    USBDISPLAY_RESOLUTION_480P = 3,
    USBDISPLAY_RESOLUTION_720P = 4,
    USBDISPLAY_RESOLUTION_1080P = 5,
    USBDISPLAY_RESOLUTION_1440P = 6,
    USBDISPLAY_RESOLUTION_2160P = 7,
} UsbDisplayResolution;

typedef enum _UsbDisplayMirrorBackStartResultCode {
    USBDISPLAY_MIRROR_BACK_START_SUCCESS = 0,
    USBDISPLAY_MIRROR_BACK_START_FAILED = 1,
    USBDISPLAY_MIRROR_BACK_START_FORBIDDEN = 2,
} UsbDisplayMirrorStartResultCode;

/**
 * 要求客户端投屏过来的画面旋转角度
 */
typedef enum _UsbDisplayRotationDegree{
    USBDISPLAY_ROTATION_DEGREE_0 = 0,
    USBDISPLAY_ROTATION_DEGREE_90 = 1,
    USBDISPLAY_ROTATION_DEGREE_180 = 2,
    USBDISPLAY_ROTATION_DEGREE_270 = 3,
} UsbDisplayRotationDegree;

/**
 * 要求客户端上传的画面是否镜像模式
 * 所谓镜像，就是画面左右对调。如果需要上下对调，就需要开启镜像的同时用前面的旋转180度。
 */
typedef enum _UsbDisplayScreenMirror{
    USBDISPLAY_SCREEN_MIRROR_DISABLED = 0,
    USBDISPLAY_SCREEN_MIRROR_ENABLED = 1,
} UsbDisplayScreenMirror;

typedef enum _UsbDisplayTransmitterType {
    USBDISPLAY_TRANSMITTER_TYPE_NORMAL = 0X00,
    USBDISPLAY_TRANSMITTER_TYPE_MANY_TO_MANY = 0X01,
} UsbDisplayTransmitterType;

typedef enum _UsbDisplayBoolean {
    USBDISPLAY_FALSE = 0x00,
    USBDISPLAY_TRUE = 0x01,
} UsbDisplayBoolean;

typedef enum _UsbDisplayNetInterface {
    USB_INTERFACE_WLAN = 0X01,
    USB_INTERFACE_ETHERNET = 0X02,
} UsbDisplayNetInterface;

typedef enum _UsbDisplayAuthorizeResult {
    AUTHORIZE_REJECT = 0X00,
    AUTHORIZE_ACCEPT = 0X01,
} UsbDisplayAuthorizeResult;

typedef struct _DeviceClient {
    /**
     * 设备的 IP 地址。会以 xxx.xxx.xxx.xxx 的形式
     */
    char ipAddress[16];

    /**
     * 设备的名字，UTF-8数据
     */
    char name[128];

    /**
     * 客户端类型。
     * clientType 的值各代表：
     * 1 PC 的传屏器
     * 2 Mac 的传屏器
     * 3 PC 的 WIFI 版软件
     * 4 Android 的客户端
     * 5 Mac的 WIFI 版客户端
     * 6 Airplay 设备
     * 7 iOS 客户端
     */
    int clientType;

    UsbDisplayTransmitterType transmitterType;

    /**
     * 客户端是否允许回控。
     */
    bool touchEnabled;

    /**
     * 鼠标加速开关。
     */
    bool mouseAccelerateEnabled;

    /**
     * 回控模式
     */
    int touchMode;

    /**
     * 分辨率
     */
    int resolution[2];
    /**
     * 音频格式
    */
    int audioFormat;

    /**
     * 音频采样率
    */
    int audioSampleRate;

    /**
      * 声道数量
    */
    int audioChannelCount;
} DeviceClient;


//=== AudioInfo

#define AUDIO_FORMAT_PCM                1
#define AUDIO_FORMAT_MP3                2
#define AUDIO_FORMAT_AAC                3
#define AUDIO_FORMAT_MP2                4

#define AUDIO_SAMPLE_RATE_44100         1
#define AUDIO_SAMPLE_RATE_48000         2

typedef enum _VideoFormat {
    USBDISPLAY_VIDEO_FORMAT_H264 = 0x01,
    USBDISPLAY_VIDEO_FORMAT_H265 = 0x02,
    USBDISPLAY_VIDEO_FORMAT_VP8  = 0X03,
    USBDISPLAY_VIDEO_FORMAT_VP9  = 0X04,
} VideoFormat;


typedef struct _AudioInfo {
    int format;
    int rate;
    int channelCount;
} AudioInfo;

typedef struct _VideoInfo {
    VideoFormat format;
} VideoInfo;

typedef struct _USBDisplayAbility {
    uint8_t frameRate;
    UsbDisplayResolution resolution;
    uint8_t gop;
    uint8_t bitrate;
} USBDisplayAbility;

typedef struct _ByomVideoInfo {
    int format; // 1: YUYV, 2:MJPG, 3:H264
    int resolution;// 1:480P, 2:720P, 3:1080P
    int fps;
} BYOMVideoInfo;

typedef struct _ByomAudioInfo {
    int format; // 1:PCM, 2:AAC, 3:MP3
    int sampleRate; // 1:44100, 2:48000
    int channelCount;
} ByomAudioInfo;

typedef struct USBDISPLAY_SDK_API _UsbDisplayCallback {
    /**
     * 当设备连接上来时，回调此接口，此时只能获取到设备的 IP
     */
    void (*onClientConnected)(DeviceClient *client);

    /**
     * 当设备断开连接时，回调此接口。
     */
    void (*onClientDisconnected)(DeviceClient *client);

    /**
     * 当设备设置了名字，回调此接口。设备的名字可能会比较长，所以此接口可能会被回调多次。
     */
    void (*onDeviceNameUpdated)(DeviceClient *client);

    /**
     * 投屏器同步唯一ID上来。
     * 一般是传屏器的Mac地址。
     */
    void (*onDeviceUpdateTransmitterId)(const char* ip, const char* transmitterId);

    /**
     * 当设备更新了它的类型（clientType）时回调此接口。
     */
    void (*onDeviceTypeUpdated)(DeviceClient *client);

    /**
     * 当设备更新了回控开关时回调此接口。此接口主要兼容旧版本。基本上传屏器和 WIFI 客户端都可以回控，其它移动设备是无法回控。
     */
    void (*onTouchUpdated)(DeviceClient *client);

    /**
     * 当设备更新了触摸模式时回调此接口。此接口主要兼容旧版本。有 PPT 模式和普通触摸模式，当时在播放 PPT 模式时，会更新为 PPT 模式，此时可以发送翻页命令让 PPT 翻页
     */
    void (*onTouchModeUpdated)(DeviceClient *client);

    /**
     * 当客户端更新屏幕分辨率时回调此接口
     */
    void (*onDeviceResolutionChanged)(DeviceClient *client);

    /**
     * 当投屏器进行了长按，回调此接口。
     * 上层应用可以根据这个事件来把其它画面下屏，相当于把当前画面全屏。
     */
    void (*onLongPressed)(DeviceClient *client);

    /**
     * 当设备请求上屏时回调此接口。此接口是在isPermitToShow之后调用，也只有在isPermitToShow返回 true 后，才会调用此接口
     */
    void (*onDeviceShow)(DeviceClient *client);

    /**
     * 当设备下屏时回调此接口。
     */
    void (*onDeviceHide)(DeviceClient *client, UsbDisplayDeviceHideType type);

    /**
     * 当设备在请求投屏时，会先回调此接口。返回 true 表示允许它上屏。返回 false 会拒绝掉它的投屏请求。
     */
    bool (*isPermitToShow)(DeviceClient *client);

    /**
     * 收到设备传输上来的 h264流时，回调此接口。buf 数据在回调完会被释放，所以如果没有立即使用，需要把数据拷贝到其它地方。
     */
    void (*onVideoFrame)(DeviceClient *client, char *buf, int length, int ts);

    /**
     * 收到设备传输上来的音频流时，回调此接口。
     * 音频采样率 44100
     * 通道数 2
     * 格式 audio/mpeg
     */
    void (*onAudioFrame)(DeviceClient *client, char *buf, int length, int ts);

    /**
     * 收到设备发送过来的声音参数。
     * 默认情况下，声音格式是mp3，采样率是44100，通道是2。
     * 如果有这个回调，那就以这个为准。
     *
     * @param client
     * @param audioInfo
     */
    void (*onAudioInfoUpdated)(DeviceClient *client, AudioInfo audioInfo);

    /**
     * 收到客户端
     * @param ip
     * @param videoInfo
     */
    void (*onVideoInfoUpdated)(const char* ip, VideoInfo videoInfo);

    /**
     * 当设备开启/关闭鼠标加速时回调此接口。请参考 QuickShare 鼠标加速。
     * 鼠标加速，可以自己在界面上画一个鼠标的图标，然后根据发送过来的鼠标位置来移动该图标。也可以调用系统的原生鼠标，然后通过一定的方式去操作它的位置。
     */
    void (*onClientRequestMouseAccelerate)(DeviceClient *client, bool val);

    /**
     * 设备发送了鼠标位置数据时回调此接口。
     * @param x 相对于设备分辨率的鼠标 X 坐标
     * @param y 相对于设备分辨率的鼠标 Y 坐标
     * 服务器这边需要根据实际情况进行转换。
     */
    void (*onClientSendMouseEvent)(DeviceClient *client, int x, int y);

    /**
     * 设备在连接成功之后，会进行一些参数的同步。当同步参数结束后会回调此接口。
     * @param client
     */
    void (*onClientSyncParameterEnd)(DeviceClient *client);

    /**
     * 客户端请求反镜像。反镜像就是把接收端的屏幕画面编码成h264发送给客户端
     * @param client
     */
    void (*onClientRequestMirrorBackStart)(DeviceClient *client);

    /**
     * 客户端请求结束反镜像
     * @param client
     */
    void (*onClientRequestMirrorBackStop)(DeviceClient *client);

    /**
     * 客户端在反镜像的时候发送Home键过来
     * @param client
     */
    void (*onClientRequestSendHomeKey)(DeviceClient *client);

    /**
     * 客户端在反镜像的时候发送Back键过来
     * @param client
     */
    void (*onClientRequestSendBackKey)(DeviceClient *client);

    /**
     * 客户端请求更新音频的音量。主要是Android客户端会使用这个接口。
     * @param ip
     * @param volume 音量值，0.0 ~ 1.0
     */
    void (*onClientRequestUpdateAudioVolume)(const char* ip, double volume);

    /**
     * 当检测到 USB 投屏器插入时回调
     */
    void (*onUsbDeviceAttached)();

    /**
     * USB 投屏器拔出时回调
     */
    void (*onUsbDeviceDetached)();

    /**
     * 当投屏器插入时，SDK 会尝试先跟它通讯，如果一切就绪了，就会回调这个接口。
     * 在这个回调之后，才可以进行版本请求、配对或者升级
     */
    void (*onUsbDeviceReady)();

    /**
     * 当获取USB 传屏器版本信息时回调
     */
    void (*onUsbDeviceRequestVersionInfoSuccess)(const char *version);

    /**
     * 当开始升级时回调
     */
    void (*onUpgradeUsbDeviceStarted)();

    /**
     * 升级投屏器进度回调
     */
    void (*onUpgradeUsbDeviceInProgress)(int progress);

    /**
     * 升级完成投屏器时回调
     */
    void (*onUpgradeUsbDeviceSuccess)();

    /**
     * 升级投屏失败时回调
     */
    void (*onUpgradeUsbDeviceFailed)(UsbDisplayErrorCode code);

    /**
     * 配对投屏器成功时回调
     */
    void (*onConfigUsbDeviceSuccess)();

    /**
     * 配对投屏器失败时回调
     */
    void (*onConfigUsbDeviceFailed)(UsbDisplayErrorCode code);

    void (*UsbDisplayLog)(UsbDisplayLogLevel level, const char *msg);

    /**
     * 当连接到投屏码服务器
     */
    void (*onConnectPinCodeServerSuccess)();

    /**
     * 当从投屏码服务器断开了
     */
    void (*onDisconnectFromPinCodeServer)();

    /**
     * 当连接投屏码服务器失败了
     * @param code
     */
    void (*onConnectPinCodeServerFailed)(UsbDisplayErrorCode code);

    /**
     * 当连接投屏码服务器成功后，投屏码服务器会分配一个投屏码。客户端根据这个投屏码就可以找到接收端的地址信息。
     * @param pinCode
     */
    void (*onReceivedPinCode)(const char* pinCode);

    /**
     * iOS客户端请求结束Airplay投屏
     * @param ip
     */
    void (*onRequestStopAirplay)(const char* ip);

    void (*onActivateSuccess)(const char* secret);

    void (*onActivateFailed)(UsbDisplayErrorCode error, const char* reason);

    /**
     * 客户端在准备投屏时，需要获取接收端对它期望的帧率、分辨率等信息
     * @param ip 请求投屏的客户端 IP
     * @param ability 需要上层对它进行赋值的 ability 对象
     */
    void (*onNewClientRequestGetAbility)(const char* ip, USBDisplayAbility* ability);

    /**
     * 客户端请求 BYOM，需要接收端返回摄像头和麦克风数据。
     * 流程上与反镜像一致。
     * @param ip
     */
    void (*onClientRequestBYOMMode)(const char* ip, const BYOMVideoInfo* videoInfo, const ByomAudioInfo * audioInfo);

    void (*onClientRequestStopByom)(const char* ip);

    void (*onClientRequestAuthorize)(const char* ip);
} UsbDisplayCallback;

typedef struct _UsbDisplaySupportFunctions {
    bool mirrorBack;
    bool snapShot;
    bool mouseAccelerate;
    bool bluetooth;
    bool annotation;
    bool audioTypePcm;
    bool audioTypeAac;
    bool notSupportFullHeight;//主要用于告诉Android客户端，不要发竖屏的码流。因为在某些平台不支持竖屏码流的解码或者显示。
    bool androidAudio;// 告诉Android客户端可以发送声音数据。一般来讲，只要不支持蓝牙的都可以打开这个选项。当Android客户端运行在Android10及以上版本时，就可以传输声音
    bool notSupportAndroidDefaultRate;//告诉Android客户端不支持默认模式，需要用帧率可调模式。
    bool supportVideoFormatH265;//接收端是否支持H265的视频格式
    bool supportVideoVP8;
    bool supportVideoVP9;
    bool supportByomMode;
} UsbDisplaySupportFunctions;


typedef struct _UsbDisplayParameter {
    /**
     * 服务端名字，用于客户端的设备检索
     */
    char serverName[128];

    /**
     * 服务端的版本。用于客户端查询版本信息
     */
    char serverVersion[40];

    /**
     * 服务端的投屏密码。客户端必须输入正确的密码后才可以进行投屏
     */
    char devicePassword[20];

    /**
     * 最大同时投屏的设备数。这个数 <= SDK 的最大投屏路数。
     */
    int maxMirroringCount;

    /**
     * 当在投屏的设备达到maxMirroringCount时，是直接拒绝掉，还是把最先投屏的设备抢掉。
     * true 表示会抢屏
     * false 表示直接拒绝后来的设备上屏。
     */
    bool racing;

    /**
     * 服务端是否支持鼠标加速。请参考QuickShare 的鼠标加速。其实就是鼠标不随视频流发送，而是单独发过来。
     */
    bool supportMouseAccelerate;

    UsbDisplayLogLevel logLevel;

    /**
     * 设置服务端的类型，发射端会根据这个类型进行一些调整
     */
    UsbDisplayReceiverType receiverType;

    /**
     * 设备服务端期望的帧率
     */
    int targetFrameRate;

    /**
     * 设置服务端期望的分辨率
     */
    UsbDisplayResolution targetResolution;

    /**
     * 设置关键帧的时间间隔，单位是『秒』。它跟帧率相关，比如帧率是15，这个 targetVideoKeyFrameInterval 值是3
     * 相当于设置给h264的参数是 15 * 3 = 45。
     * 设置为0或者不设置，代表不修改，由客户端自己定
     */
    uint8_t targetVideoKeyFrameInterval;

    /**
     * 设置视频的码率，单位是 100KB/s。比如它的值是6，那么就相当于 600 KB/s
     * 那么设置给h264的码率参数就相当于 6 * 100 * 8 = 4800kbps
     * 设置为0或者不设置，代表不修改，由客户端自己定
     */
    uint8_t targetVideoBitRate;

    UsbDisplayRotationDegree rotationDegree;

    UsbDisplayScreenMirror screenMirror;

    UsbDisplayBoolean discoverable;

    UsbDisplayBoolean airplayDiscoverable;

    /**
     * 激活时使用的网络接口，代表 @mac 是使用哪个网卡的地址
     */
    UsbDisplayNetInterface interface;
    /**
     * 网卡地址
     */
    char mac[20];
    /**
     * 当首次启动时，赋值为空，SDK在激活成功后会回调这个密钥信息，后续启动就把之前回调的信息填在这里
     */
    char secret[48];
    /**
     * 激活码。在未激活时需要填入，后续可以不用填。
     */
    char code[20];

    /**
     * 客户码信息，用于区分不同的客户。
     */
    char customerCode[48];

    /**
     * 平台信息。用于区分不同的平台。
     */
    char platformType[48];

    UsbDisplayCallback cbs;
    UsbDisplaySupportFunctions functions;
} UsbDisplayParameter;

typedef enum _UsbDisplayTouchAction {
    USBDISPLAY_TOUCH_DOWN = 0x00,
    USBDISPLAY_TOUCH_MOVE = 0x01,
    USBDISPLAY_TOUCH_UP = 0x02
} UsbDisplayTouchAction;

typedef struct _UsbDisplayTouchEvent {
    UsbDisplayTouchAction action;
    int id;
    int rawX;
    int rawY;
} UsbDisplayTouchEvent;

typedef struct _UsbDisiplayConfigInfo {
    char ssid[40];
    char password[40];
    char targetIPAddress[40];
    bool hidden;
    bool noPassword;
} UsbDisplayConfigInfo;

typedef struct UsbDisplaySdk UsbDisplayContext;


/**
 * 初始化，这个函数必须在其它函数之前调用。
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayInit(UsbDisplayContext **context,
                                                      UsbDisplayParameter parameter);

/**
 * 启动服务。
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayStart(UsbDisplayContext *context);

/**
 * 停止服务
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayStop(UsbDisplayContext *context);

/**
 * 让某个正在投屏的设备下屏。如果此设备当前不在投屏，此调用无作用
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayKickOut(UsbDisplayContext *context,
                                                         const char *ip);

/**
 * 让某个设备上屏。如果此设备已经在投屏，此调用无效。
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayShow(UsbDisplayContext *context,
                                                      const char *ip);

/**
 * 触摸反控某个设备。
 * @param ip 目标客户端的 IP 地址
 * @param offsetX 视频内容在View 上的X轴偏移位置
 * @param offsetY 视频内容在 View 上的Y轴偏移位置
 * @param viewWidth 在界面上，此设备显示的宽度
 * @param viewHeight 在界面上，此设备显示的高度
 * @param pointCount 回控的点数
 * @param events 回控的数据。
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayTouch(UsbDisplayContext *context,
                                                       const char *ip,
                                                       int offsetX,
                                                       int offsetY,
                                                       int viewWidth,
                                                       int viewHeight,
                                                       int pointCount,
                                                       UsbDisplayTouchEvent events[]);

/**
 * 键盘按下某个按键，然后回传到某个设备。
 * @param ip 目标客户端的 IP 地址
 * @param keyCode 按键码
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayKeyDown(UsbDisplayContext *context,
                                                         const char *ip,
                                                         UsbDisplayKeyCode keyCode);
/**
 * 键盘抬起某个按键，然后回传到某个设备。
 * @param ip 目标客户端的 IP 地址
 * @param keyCode 按键码
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayKeyUp(UsbDisplayContext *context,
                                                       const char *ip,
                                                       UsbDisplayKeyCode keyCode);

/**
 * 键盘按下某个功能按键，然后回传到某个设备。
 * @param ip 目标客户端的 IP 地址
 * @param keyCode 按键码
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayFunctionKeyDown(UsbDisplayContext *context,
                                                                 const char *ip,
                                                                 UsbDisplayFunctionKey keyCode);

/**
 * 键盘抬起某个功能按键，然后回传到某个设备。
 * @param ip 目标客户端的 IP 地址
 * @param keyCode 按键码
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayFunctionKeyUp(UsbDisplayContext *context,
                                                               const char *ip,
                                                               UsbDisplayFunctionKey keyCode);

/**
 * 更新名字和密码。更新之后，在检索列表上看到的名字会不一样。所有已经连上来的非 Dongle 客户端都需要重新认证。
 * 正在投屏的非 Dongle客户端会被下屏。
 * @param authorize 上屏是否需要授权
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayUpdate(UsbDisplayContext *context,
                                                        const char *name,
                                                        const char *password,
                                                        UsbDisplayBoolean discoverable,
                                                        UsbDisplayBoolean authorize);

USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayUpdateSupportFunctions(UsbDisplayContext* context,
                                                     const UsbDisplaySupportFunctions& functions);

/**
 * 请求获取投屏的版本信息。这里是异步调用，会从 @onUsbDeviceRequestVersionInfoSuccess 返回结果。
 * @param context
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayRequestGetVersion(UsbDisplayContext *context);

/**
 * 请求获取投屏的版本号信息。
 * 其实也就是 @UsbDisplayRequestGetVersion 把版本转换成 int。另外这个函数是同步的
 * @param context
 * @return
 */
USBDISPLAY_SDK_API int UsbDisplayRequestGetVersionCode(UsbDisplayContext *context);





/**
 * 请求升级投屏器，传入投屏器固件的目录路径
 * @param context
 * @param path
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayRequestUpgrade(UsbDisplayContext *context,
                                                                const char *path);

/**
 * 配对投屏器。传入需要配对的信息
 * @param context
 * @param info
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplayRequestConfigUsbDevice(UsbDisplayContext *context, UsbDisplayConfigInfo *info);


/**
 * 获取SDK 的版本
 * @return
 */
USBDISPLAY_SDK_API const char *UsbDisplayGetSdkVersion();

/**
 * 请求客户端调帧率
 * @param ip
 * @param frameRate 帧率。设置投屏客户端的帧率
 * @param resolution 分辨率。请按规定的常量设置分辨率
 * @param targetKeyFrameInterval 关键帧间隔。设置为0表示按默认设置
 * @param targetVideoBitRate 视频的码率，设置为0表示按默认设置
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplayRequestUpdateTargetFrameRate(
        UsbDisplayContext *context,
        const char *ip,
        int frameRate,
        UsbDisplayResolution resolution,
        uint8_t targetKeyFrameInterval,
        uint8_t targetVideoBitRate,
        UsbDisplayRotationDegree rotationDegree,
        UsbDisplayScreenMirror screenMirror
);

/**
 * 设置帧率。当前所有连接都会收到这个更新，同时后续连接上来的也会按这个帧率
 * @param context
 * @param frameRate
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplayRequestUpdateGlobalTargetFrameRate(
        UsbDisplayContext *context,
        int frameRate,
        UsbDisplayResolution resolution,
        uint8_t targetKeyFrameInterval,
        uint8_t targetVideoBitRate,
        UsbDisplayRotationDegree rotationDegree,
        UsbDisplayScreenMirror screenMirror
);

/**
 * 请求客户端发送关键帧
 * @param ip
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayRequestKeyFrame(UsbDisplayContext *context, const char *ip);

/**
 * 在客户端请求反镜像后，需要需要接收端在准备好给它发送反镜像数据时，发这个命令，让它可以开始解码数据了。
 * @param context
 * @param ip
 * @param code
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayRequestMirrorDisplayResult(UsbDisplayContext *context, const char *ip,
                                                                            UsbDisplayMirrorStartResultCode code);

/**
 * 给客户端发送反镜像的h264视频数据
 * @param context
 * @param ip
 * @param buf
 * @param length
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplaySendMirrorBackStream(UsbDisplayContext *context, const char *ip, const char *buf,
                               int length, int timestamp);


/**
 * 给客户端发送反镜像的音频流数据
 * @param context
 * @param ip
 * @param buf
 * @param length
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplaySendMirrorBackAudioStream(UsbDisplayContext *context,
                                    const char *ip,
                                    const char *buf,
                                    int length,
                                    int timestamp);

/**
 * 给客户端发送 BYOM 的视频格式
 * @param context
 * @param ip 目标客户端的IP
 * @param videoInfo @see ByomVideoInfo
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplaySendByomVideoInfo(UsbDisplayContext* context,
                                  const char* ip,
                                  const BYOMVideoInfo videoInfo);

/**
 * 给客户端发送 BYOM 视频数据。
 * @param context
 * @param ip 目标客户端地址
 * @param buf 数据buffer
 * @param length 长度
 * @param timestamp 时间戳
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplaySendByomVideoData(UsbDisplayContext* context,
                            const char* ip,
                            const char* buf,
                            int length,
                            int timestamp);

/**
 * 给客户端发送 BYOM 的音频格式信息
 * @param context
 * @param ip 目标客户端地址
 * @param audioInfo
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplaySendByomAudioInfo(UsbDisplayContext* context,
                            const char* ip,
                            const ByomAudioInfo audioInfo);

USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplaySendByomAudioData(UsbDisplayContext* context,
                            const char* ip,
                            const char* buf,
                            int length,
                            int timestamp);

/**
 * 请求客户端打开或者关闭鼠标加速。0表示关闭，1表示打开。
 * @param context
 * @param ip 目标设备的IP
 * @param enable 0表示关闭，1表示打开
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode UsbDisplayRequestMouseAccelerate(UsbDisplayContext* context, const char* ip, int enable);


/**
 * 连接投屏码服务器，启动6位投屏码功能
 * @param context
 * @param address 投屏码服务器地址
 * @param port 投屏码服务器端口
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplayConnectPinCodeServer(UsbDisplayContext *context, const char* address, int port);

/**
 * 停止投屏码服务器
 * @param context
 * @return
 */
USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplayDisconnectPinCodeServer(UsbDisplayContext *context);


/**
 * 获取升级固件包的版本信息。这里是同步调用。
 * @param context
 * @return
 */
USBDISPLAY_SDK_API const char*
UsbDisplayGetFirmwareVersion(UsbDisplayContext *context, const char* firmwarePath);


/**
 * 获取升级固件包的版本信息。这里是同步调用。
 * @param context
 * @return
 */
USBDISPLAY_SDK_API int
UsbDisplayGetFirmwareVersionCode(UsbDisplayContext *context, const char* firmwarePath);

USBDISPLAY_SDK_API UsbDisplayErrorCode
UsbDisplaySendAuthorizeResult(UsbDisplayContext *context,
                              const char* ip,
                              UsbDisplayAuthorizeResult result);

#ifdef __cplusplus
}
#endif  /* __cplusplus */

#endif //ANDISPLAYSDK_USBDISPLAYRECEIVER_H
